package com.wuku.stater.redis.redisClient;

import java.util.ArrayList;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wuku.stater.redis.properties.RedisProperties;
import com.wuku.stater.redis.service.RedisService;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisClient extends RedisService {
	private static Logger logger = LoggerFactory.getLogger(JedisClient.class);
	
	
	public JedisClient(RedisProperties redisProperties) {
		super(redisProperties);
	}

	private JedisPool pool;

	private JedisPool getJedisPool() {
		if (pool == null) {
			pool = createPool();
		}
		return pool;
	}

	private JedisPool createPool() {
		JedisPool jedisPool = null;
		String host = redisProperties.getHost();
		int port = redisProperties.getPort();
		String password = redisProperties.getPassword();
		int timeout = redisProperties.getTimeOut();

		try {
			JedisPoolConfig config = new JedisPoolConfig();
			config.setMaxTotal(-1);

			// Set the minimum number of idle connections to 8 to ensure that there are at least 8 idle connections
			config.setMinIdle(8);
			// Set the maximum number of idle connections to integer.max'value to ensure that new connections will not be disconnected immediately when they are used up
			config.setMaxIdle(Integer.MAX_VALUE);
			// Set the cleanup interval; if it is negative, the eviction thread will not run
			config.setTimeBetweenEvictionRunsMillis(180000);
			// Set the minimum idle time of the connection to 5 minutes. If the idle time exceeds this time and the number of idle connections is greater than the minimum number, it will be marked as cleanable
			config.setSoftMinEvictableIdleTimeMillis(300000);
			// Set the eviction time to the maximum value to shield the hard eviction behavior
			config.setMinEvictableIdleTimeMillis(Long.MAX_VALUE);
			// Set to block when there is no connection, and keep waiting to ensure that no exception is thrown
			config.setBlockWhenExhausted(true);
			config.setMaxWaitMillis(-1);
			// Let threads first come, first served to avoid no response
			config.setFairness(true);

			// Check the validity when getting the connection, false by default
			config.setTestOnBorrow(false);
			config.setTestOnReturn(true);
			// Check the validity when getting the connection, false by default
			config.setTestWhileIdle(true);

			jedisPool = new JedisPool(config, host, port, timeout, password);

			// Preassigned connections
			int i = 0;
			ArrayList<Jedis> arrJedis = new ArrayList<>();
			for (i = 0; i < config.getMinIdle(); i++) {
				arrJedis.add(jedisPool.getResource());
			}

			for (i = 0; i < config.getMinIdle(); i++) {
				arrJedis.get(i).close();
			}

		} catch (Exception e) {
			logger.error("{}", e);
		}
		return jedisPool;
	}


	@Override
	public String set(String key, String value) {

		Jedis redisClient = getJedisPool().getResource();
		redisClient.set(key, value);
		redisClient.close();
		return null;
	}


	@Override
	public String get(String key) {

		Jedis redisClient = getJedisPool().getResource();
		String string = redisClient.get(key);
		redisClient.close();
		return string;
	}


	@Override
	public Map<String, String> hgetAll(String key) {

		Jedis redisClient = getJedisPool().getResource();
		Map<String, String> hgetAll = redisClient.hgetAll(key);
		redisClient.close();
		return hgetAll;

	}


	@Override
	public Set<String> smembers(String key) {

		Jedis redisClient = getJedisPool().getResource();
		Set<String> smembers = redisClient.smembers(key);
		redisClient.close();
		return smembers;

	}


	@Override
	public boolean sismember(String key, String member) {

		Jedis redisClient = getJedisPool().getResource();
		Boolean sismember = redisClient.sismember(key, member);
		redisClient.close();
		return sismember;

	}

	@Override
	public Long sadd(String key, String... members) {

		if (members == null || members.length < 1) {
			return 0L;
		}

		Jedis redisClient = getJedisPool().getResource();
		Long sadd = redisClient.sadd(key, members);
		redisClient.close();
		return sadd;
	}


	@Override
	public Long ttl(String key, int ttl) {
		Jedis redisClient = getJedisPool().getResource();
		Long expire = redisClient.expire(key, ttl);
		redisClient.close();
		return expire;
	}


	@Override
	public boolean ttl(int ttl, String... keys) {
		Jedis redisClient = getJedisPool().getResource();
		for (String key : keys) {
			redisClient.expire(key, ttl);
		}
		redisClient.close();
		return true;
	}

}
